home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / MISC / OPTIMIZE.ZIP / OPTIMIZE.TXT
Encoding:
Text File  |  1996-03-16  |  11.0 KB  |  257 lines

  1. This article was published as:
  2.  
  3. "Game Size: The Forgotten Discipline"
  4.  PC Techniques, Vol. 6, no 3
  5.  Aug/Sept. 1995, page 93.
  6.  
  7. What appears here is the original manuscript, as submitted to Jeff
  8. Duntemann. Any changes in the published version are due to Jeff's
  9. expert editing.
  10.  
  11.  
  12.                         Writing Smaller Games
  13.                      copyright 1995 Diana Gruber
  14.  
  15. At a recent conference, I ran into a user of a shareware game who
  16. was complaining that the game wouldn't run on his ancient 80286
  17. computer. It was running too fast. The program, apparently, was
  18. written years earlier to run on an XT, and performed badly on
  19. anything faster. He was wondering if I had any suggestions on how
  20. to fix it. I didn't, but I took the opportunity to recall the good
  21. old days of game programming, when developers knew how to get the
  22. most out of those old, primitive systems.
  23.  
  24. The thing that sticks in my mind the most about the early days
  25. of game programming was how much attention we paid to the size
  26. of a game. These days, all the emphasis is on speed. If a game
  27. fits on ten floppy disks or a CD-ROM, it isn't a problem. We
  28. can afford to be wasteful where size is concerned, as long as
  29. we have adequate speed.
  30.  
  31. Do you remember when floppy disks were so expensive that games
  32. had to fit single 360K disk? Disk space wasn't the only problem
  33. back then. You couldn't count on a system having 640K bytes of
  34. memory, or even 512K. To reach the widest audience, a game
  35. had to run in 256K or less.
  36.  
  37. Programming to those types of minimal configurations is becoming
  38. a lost art. Game programmers who remember how it was done still
  39. have the necessary skills. We remember how to optimize for size.
  40. But you don't see much written on the subject, because it is
  41. no longer an issue like it used to be. Still, there is no reason
  42. to be sloppy. Wasted space is wasted space. Even if you don't
  43. need to optimize for size, it still pays to know how to do it.
  44. And there are still occasions where optimizing for size is
  45. important, for example when writing code for an embedded system
  46. or an EPROM. 
  47.  
  48. With this in mind, I am offering the following list of suggestions
  49. for optimizing games for size.
  50.  
  51. Use C, not C++
  52.  
  53. C++ is a powerful language. While you can use it without a speed
  54. degradation, you will most likely notice an increase in the size
  55. of your program. When optimizing for size, use C, stripped down
  56. to the bare minimum. Also, compare compilers. Some compilers
  57. generate smaller code than others.
  58.  
  59. Check your compiler switches
  60.  
  61. Most compilers give you a choice between optimizing for speed and
  62. optimizing for size. Choose optimizing for size, and be sure to
  63. turn off the debugging information. Keep an eye on things like
  64. stack size and heap size, and adjust as appropriate.
  65.  
  66. Be careful with overlays
  67.  
  68. The big problem with overlays is the number of disk accesses they can
  69. generate. If these are not planned carefully, your program will
  70. access the hard disk constantly, causing your program to run very
  71. slowly. However, if used correctly, overlays can be a wonderful way
  72. to keep a game running when RAM is low.
  73.  
  74. Use the medium memory model if possible
  75.  
  76. You want your data to default to near memory. You can fit a lot
  77. of data in a 64K segment, especially if you make heavy use of globals
  78. and reuseable arrays. If Windows Write can be written in medium
  79. model, so can your game. The small model is also good, but it is usually
  80. not practical to fit both code and data into 64K segments.
  81.  
  82. Use the smallest integral type
  83.  
  84. Don't use long integers when short integers will do. Don't use short
  85. integers when bytes will do. This isn't terribly important where
  86. individual variables are concerned, but pay careful attention to your
  87. arrays.
  88.  
  89. Use globals
  90.  
  91. These days, programmers are taught to avoid globals for stylistic
  92. reasons. However, they can actually be quite efficient, both in
  93. terms of speed and size. There is a time and a place for everything.
  94. If you are writing a program for a bank that 20 other programmers
  95. are going to work on, you should avoid using globals. If you are
  96. writing a game and you want to squeeze every drop of performance
  97. out of it, use them liberally.
  98.  
  99. Use malloc() and free()
  100.  
  101. This is obvious. When an object, such as a bitmap or a sound effect,
  102. is no longer in use, its space should be available for some other
  103. object to use. A variation on this is to allocate all the free memory
  104. at the beginning of your program, and control the use of it yourself.
  105. Programmers often write functions called my_malloc() and my_free()
  106. which simply keep track of pointers to this block of memory. However
  107. you choose to manage memory, be careful about fragmenting it.
  108.  
  109. Reuseable arrays
  110.  
  111. Allocate an array of a few thousand bytes and use it over and over.
  112. Temporary bitmaps, such as menu art, can go in there, along with
  113. sound effects, masking maps, or whatever else comes and goes
  114. frequently.
  115.  
  116. Write lots of small functions
  117.  
  118. Any time you do something more than twice, write another function
  119. to handle it. The overhead of using many function calls can be
  120. offset by the liberal use of global variables.
  121.  
  122. Don't use inline functions
  123.  
  124. Inline functions are the way to squeeze more speed out of a C++
  125. program. In some cases, class functions default to inline. This
  126. adds size to your program, because every occurrence of the function
  127. call is expanded to the whole function at compile time. 
  128.  
  129. Use macros sparingly
  130.  
  131. Do this for the same reason you avoid using inline functions. The
  132. macro substitution happens at compile time, adding size to your
  133. executable program. Don't avoid macros altogether, though. They can
  134. greatly simplify your code, and add a speed boost as well. Just
  135. be careful how you use them.
  136.  
  137. Don't use unrolled loops
  138.  
  139. Unrolled loops are a speed optimization, at the expense of program
  140. size. If size is a concern, roll them back up. A compromise solution
  141. is to use partial unrolling. For example, you can execute a
  142. 1000-iteration loop 500 times but include the code twice within the
  143. loop.
  144.  
  145. Don't use compiled bitmaps
  146.  
  147. Compiled bitmaps are all the rage these days. Bitmap data is turned
  148. into assembly language instructions. They are blazingly fast, but
  149. add massive size overhead to the size of your program.
  150.  
  151. Use itoa() instead of sprintf()
  152.  
  153. There are very few times when you want formatted text output in a
  154. game. Usually the score will contain integers, and maybe some
  155. inventory or map coordinates also involve numbers. The sprintf()
  156. function does a nice job of converting numbers to text, but it
  157. also does a lot more. The unneeded code adds to the size of your
  158. program. If possible, avoid it and use itoa(). Similarly, use atoi()
  159. instead of sscanf().
  160.  
  161. Don't use floating point
  162.  
  163. This is a universal truth in games, and programmers will go to great
  164. lengths to avoid floating point math, including writing their own
  165. "fixed point" functions, which are integer simmulations of real number
  166. functions. In general, integer solutions can be found to most
  167. game design problems, usually without resorting to fixed point.
  168. For example, to turn clock ticks into seconds, you need to multiply
  169. by 18.2. This can be accomplished by multiplying by 182 and dividing
  170. by 10.
  171.  
  172. Rewrite the startup code
  173.  
  174. While I have never done this, some game programmers do it routinely.
  175. The function c0.asm can be optimized by stripping out the code you
  176. don't need.
  177.  
  178. Compress your executable
  179.  
  180. There is a freeware program called LZEXE which allows you to store
  181. your executable in a compressed format which is decompressed at load
  182. time. This saves disk space, but not RAM. The program will expand
  183. to fill up the same amount of RAM it required before the compression.
  184. There are also commercial programs that do the same job.
  185.  
  186. Use repetitive music and brief sound effects
  187.  
  188. Music and sound effects will eat up huge chunks of space. Plan these
  189. carefully. Trim them down to the bare minimum, and store them in
  190. RAM in reuseable arrays.
  191.  
  192. Turn little files into big files
  193.  
  194. Files are stored on disks in allocation units. Typically, DOS will
  195. alocate a unit of two 512-byte sectors on a floppy disk, or four
  196. sectors on a hard disk. A tiny file will fill the entire allocation
  197. unit, even if it is only a few bytes long. The rest of the
  198. allocation unit is simply unused space. On average, 512 bytes of space is
  199. wasted for each file on a floppy disk. That means if you have 10
  200. files on a floppy disk, you have approximately 5K of wasted space. So
  201. if you can combine your bitmaps or sound effects into larger binary
  202. files, you will achieve a significant savings in disk space.
  203.  
  204. Use reuseable artwork
  205.  
  206. If your title screen and your credit screen use the same artwork, but 
  207. perhaps arranged differently, you can store it in a single file and
  208. organize it at run time. If your title screen uses artwork from the
  209. game, so much the better. Recycle those files as much as possible.
  210.  
  211. Strip the palette information out of PCX files
  212.  
  213. If you use the same color palette throughout the game, then you
  214. don't need to store that information in a PCX file. The 256-color PCX
  215. files have 768 bytes at the end which hold the palette information.
  216. You can trim that off. If you have 10 PCX files all using the same
  217. palette, this will save you more than 7K.
  218.  
  219. Use RLE bitmaps
  220.  
  221. Run Length Encoding (RLE) is a simple technique for compressing
  222. bitmaps. It simply records the color, then the number of pixels of
  223. that color, in a continuous pattern starting at one corner. Depending
  224. on the artwork, this can save you considerable space both both in
  225. terms of disk space and RAM. RLE's are also very efficient in terms
  226. of speed. They can be displayed faster than an uncompressed bitmap,
  227. but not as fast as a compiled bitmap.
  228.  
  229. Don't store text as graphics
  230.  
  231. If you have a page of text, for example opening credits or a storyline,
  232. store it as character strings and display it using a bitmapped font.
  233. Don't store it in a PCX file, which would be very wasteful.
  234.  
  235. Split your sprites
  236.  
  237. If you have two sprites that are almost identical, break them up.
  238. For example, if you have a man with his hands up, and the same man
  239. with his hands down, make the man one sprite, and the hands another
  240. sprite. This will save quite a bit of sprite storage room, but
  241. it causes a slight speed degradation (you turn one blit into two blits)
  242. and it is also time-consuming and annoying to manipulate the artwork
  243. that way. If you are at the end of the development cycle, and you
  244. just need to squeeze a few more bytes out of your program, this is
  245. a good place to do it.
  246.  
  247. As you can see, many of these tips are exactly the opposite of what
  248. you would do if you were optimizing for speed. In actual practice,
  249. game programmers tend to weigh their options and make decisions based
  250. on both size and speed. These days, the equation is skewed heavily
  251. toward speed, with size being a trivial factor in development
  252. decisions. Still, it pays to know what you are trading away when you
  253. make your tradeoff decisions. A good programmer will keep both size
  254. and speed considerations in mind when designing and developing games.
  255.  
  256.  
  257.